import Config from "@/config";
import { LooseObject } from "@/entity";

/* #ifdef H5 */
import axios, { AxiosPromise } from "axios";
/* #endif */

/** 被选中的文件对象 */
interface FileData {
  /** 微信返回文件路径 */
  filePath: string;
  /** 要设定的文件名 */
  name: string;
}

interface httpConfig {
  /** 基础路径 */
  baseURL?: string;
  /** 请求路径 */
  url: string;
  /** 请求参数 */
  data?: { file?: FileData[]; [key: string | number]: any } | string;
  /** 请求头 */
  header?: { [key: string | number]: any };
  /** 超时时间 */
  timeout?: number;
  /** 请求方式 */
  method?: "GET" | "POST" | "OPTIONS" | "HEAD" | "PUT" | "DELETE" | "TRACE" | "CONNECT" | undefined;
  /** 请求数据格式 */
  dataType?: "json" | undefined;
  /** 响应数据格式 */
  responseType?: "text" | "arraybuffer" | undefined;
}

/* #ifdef MP-WEIXIN */
/** 请求库 */
function http<T>({ baseURL = Config.baseURL, url = "", data = {}, header = {}, timeout = 30 * 1000, method = "POST", dataType = "json", responseType = "text" }: httpConfig): Promise<T> {
  let newHeader: LooseObject = {
    // 'content-type': 'application/json'
  };
  newHeader = Object.assign(newHeader, header);
  return new Promise((resolve, reject) => {
    try {
      wx.request({
        url: `${baseURL}${url}`,
        data,
        header: newHeader,
        timeout,
        method,
        dataType,
        responseType,
        success({ data, statusCode, header, cookies, profile }) {
          if (statusCode === 200) {
            resolve(data as Promise<T>);
          } else {
            switch (statusCode) {
              case 401:
                uni.reLaunch({ url: "/pages/login/login" });
                break;
              default:
                reject();
                break;
            }
          }
        },
        fail(error) {
          console.error("http fail", error);
          reject(error);
        },
        complete() {},
      });
    } catch (error) {
      reject(error);
    }
  });
}
/* #endif */

/* #ifdef H5 */
const axiosInstance = axios.create({
  baseURL: "/api",
  withCredentials: true,
});
function http2<T>({ baseURL = Config.baseURL, url = "", data = {}, header = {}, timeout = 30 * 1000, method = "POST", dataType = "json", responseType = "text" }: httpConfig): Promise<T> {
  return new Promise((resolve, reject) => {
    if (method === "POST") {
      let formData = new FormData();
      for (const key in data as any) {
        if (Object.prototype.hasOwnProperty.call(data, key)) {
          const item = data[key];
          formData.append(key, item);
        }
      }
      return axiosInstance
        .post(url, formData)
        .then((res) => {
          resolve(res.data);
        })
        .catch((error) => {
          reject(error);
        });
    } else {
      return axiosInstance
        .get(url, {
          params: {
            ...(data as object),
          },
        })
        .then((res) => {
          resolve(res.data);
        })
        .catch((error) => {
          reject(error);
        });
    }
  });
}
/* #endif */
let request: <T>(httpConfig: httpConfig) => Promise<T>;
/* #ifdef MP-WEIXIN */
request = http;
/* #endif */

/* #ifdef H5 */
request = http2;
/* #endif */

/**
 * @auth NoahLiu
 * @team 星城前端团队
 * @description 请求对象，在H5端使用axios，微信端直接封装 uni.request，如果项目要求传递 formData 建议使用 uni.upload 上传文件接口，要不然ios会有栈溢出的bug
 */
export default request;
